#include "mp3_encoder.h"
#include "lame.h"

int Mp3Encoder::Init(const char* pcmFilePath,
        const char *mp3FilePath,
        int sampleRate, int channels, int bitDepth) {
    this->pcm_sample_rate = sampleRate;
    this->pcm_channels = channels;
    this->pcm_bit_depth = bitDepth;

    int ret = -1;
    pcmFile = fopen(pcmFilePath, "rb");
    if (pcmFile) {
        mp3File = fopen(mp3FilePath, "wb");
        if (mp3File) {
            lameClient = lame_init();
            lame_set_num_channels(lameClient, channels);
            lame_set_in_samplerate(lameClient, sampleRate);

            lame_set_out_samplerate(lameClient, sampleRate);
            lame_set_brate(lameClient, 192);
            lame_set_quality(lameClient, 2);
            ret = lame_init_params(lameClient);
        }
    }
    return ret;
}

int Mp3Encoder::Encode(){
    // 单声道处理
    int result = 0;
    if (this->pcm_channels == 1) {
        int bufferSize = 1024 * 16;
        auto* buffer = new short[bufferSize/2];
        size_t readBufferSize = 0;
        unsigned char* mp3_buffer = new unsigned char[bufferSize];
        while ((readBufferSize = fread(buffer, sizeof(short), bufferSize/2, pcmFile)) > 0){
            LOGI("read buffer size: %d", readBufferSize);
            size_t encodeSize = lame_encode_buffer(lameClient, 
                    (short int*)buffer, NULL, readBufferSize,
                    mp3_buffer, bufferSize);
            LOGI("encode size: %d", encodeSize);
            if (encodeSize >= 0) {
                fwrite(mp3_buffer, 1, encodeSize, mp3File);
            } else {
                result = encodeSize;
                LOGE("encode fail, encode code:%d", encodeSize);
                break;
            }
        }
        delete[] buffer;
        delete[] mp3_buffer;
    } else if (this->pcm_channels == 2) {
        //双声道处理
        int bufferSize = 1024 * 16;
        short* buffer = new short[bufferSize/2];
        short* leftBuffer = new short[bufferSize / 4];
        short* rightBuffer = new short[bufferSize / 4];
        unsigned char* mp3_buffer = new unsigned char[bufferSize];
        size_t readBufferSize = 0;
        while ((readBufferSize = fread(buffer, sizeof(short), bufferSize/2, pcmFile)) > 0) {
            LOGI("read buffer size: %d", readBufferSize);
            for (int i=0; i < readBufferSize; i++) {
                if (i%2 == 0) {
                    leftBuffer[i/2] = buffer[i];
                } else {
                    rightBuffer[i/2] = buffer[i];
                }
            }
            size_t encodeSize = lame_encode_buffer(lameClient,
                    (short int *)leftBuffer, (short int *)rightBuffer,
                    (int)(readBufferSize / 2), mp3_buffer, bufferSize);
            LOGI("encode size: %d", encodeSize);
            if (encodeSize > 0) {
                fwrite(mp3_buffer, 1, encodeSize, mp3File);
            } else {
                result = encodeSize;
                LOGE("encode fail, encode code:%d", encodeSize);
                break;
            }
        }
        delete[] buffer;
        delete[] leftBuffer;
        delete[] rightBuffer;
        delete[] mp3_buffer;
    } else {
        LOGE("encode fail, not support channels:%d", this->pcm_channels);
        result = -5;
    }
    return result;
}


void Mp3Encoder::Destroy() {
    if (pcmFile) {
        fclose(pcmFile);
    }
    if (mp3File) {
        fclose(mp3File);
        lame_close(lameClient);
    }
}

Mp3Encoder::Mp3Encoder() = default;

Mp3Encoder::~Mp3Encoder() = default;

